home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / DELPHI32 / CALCULTR / MCALC / TREEVIEW.PAS < prev   
Pascal/Delphi Source File  |  1996-07-24  |  15KB  |  492 lines

  1. (*              TreeView-32 Calculator Interface Unit (Object Pascal)
  2.                            (c) Daniel Doubrovkine
  3.   Stolen Technologies Inc. - University of Geneva - 1996 - All Rights Reserved
  4.             for Scientific Calculator, version revised on 01.07.96
  5.        (part of the Expression Calculator 2.0 and of RecordIt 1.0 beta)
  6.  
  7.      last minute's note: I won't be surprised if there were bugs in this unit
  8. *)
  9. unit TreeView;
  10.  
  11. interface
  12.  
  13. type
  14.     {type definitions for TNode object}
  15.     ContentsType=(NodeVariable,NodeOperator,NodeSingle,NodeValue);
  16.     ContentsPtr=^Contents;
  17.     Contents=record
  18.      MyVariable:string;
  19.      MyOperator:string;
  20.      MySingle:string;
  21.      MyValue:extended;
  22.               end;{contents record}
  23.     {PNode is the pointer to the TNode object}
  24.     PNode= ^TNode;
  25.     {TNode object itself, assembly of TNodes make a non-circular tree with }
  26.     {any number of children & brothers                                     }
  27.     TNode=object
  28.         {field definitions}
  29.            NodeContents:ContentsPtr;       {Node contents, variable, op or value}
  30.            NodeType:ContentsType;          {Node type, variable, op or value}
  31.            ParentNodePtr:PNode;            {pointer to parent TNode:PNode}
  32.            BrotherNodePtr:PNode;           {pointer to next brother TNode:PNode}
  33.            ChildNodePtr:PNode;             {pointer to first child TNode:PNode}
  34.            {methods definitions, see later for deeper discussion}
  35.            constructor Create(ContentsType:ContentsType;Value:string);
  36.            destructor  Destroy;
  37.            function    AddChild(ContentsType:ContentsType;Value:string):PNode;
  38.            function    AddBrother(ContentsType:ContentsType;Value:string):PNode;
  39.            function    RemoveChild(ItemPosition:integer):boolean;
  40.            function    RemoveBrother(ItemPosition:integer):Boolean;
  41.            function    Child(ItemCount:integer):Pnode;
  42.            function    Brother(ItemCount:integer):Pnode;
  43.            function    Contents:string;
  44.            function    Parent:PNode;
  45.            procedure   Show;
  46.            procedure   ShowLevel(level:integer;var ShowString:string);
  47.            function    ChildCount:integer;
  48.            function    Index:integer;
  49.            function    BrothersCount:integer;
  50.            function    Remove:Boolean;
  51.            function    FindItem(MyContentsType:ContentsType;MyValue:string):PNode;
  52.            function    InsertLevel(BItem:PNode):PNode;
  53.         end;{TNode object ends here}
  54.  
  55. implementation
  56.  
  57. uses Dialogs;
  58.  
  59. {TNode object methods definitions}
  60. {
  61.  NAME:          TNode.FindItem
  62.  INPUT:         Node Type:ContentsType, Node Contents:String
  63.  OUTPUT:        PNode
  64.  PURPOSE:       Parses the whole tree and returns an item matching the request
  65.                 returns nil if no such item has been found
  66. }
  67. function TNode.FindItem(MyContentsType:ContentsType;MyValue:string):PNode;
  68. var
  69.    FoundItem:PNode;
  70. begin
  71.    FoundItem:=nil;
  72.    if (NodeType=MyContentsType) and (Contents=MyValue) then begin
  73.       FindItem:=@Self;
  74.       exit;
  75.       end;
  76.    if ChildNodePtr<>nil then FoundItem:=ChildNodePtr^.FindItem(MyContentsType,MyValue);
  77.    if FoundItem<>nil then begin
  78.       FindItem:=FoundItem;
  79.       exit;
  80.       end;
  81.    if BrotherNodePtr<>nil then FoundItem:=BrotherNodePtr^.FindItem(MyContentsType,MyValue);
  82.    if FoundItem<>nil then begin
  83.       FindItem:=FoundItem;
  84.       exit;
  85.       end;
  86.       FindItem:=FoundItem;
  87.    end;
  88.  
  89. {
  90.  NAME:          TNode.Remove
  91.  INPUT:         void
  92.  OUTPUT:        Boolean (True=operation successful)
  93.  PURPOSE:       Attempts to remove the whole TNode, needs to have a parent
  94.                 pointer, all top tree items don't have any
  95. }
  96. function TNode.Remove:Boolean;
  97. begin
  98.    Remove:=False;
  99.    if ParentNodePtr=nil then exit;
  100.    Remove:=ParentNodePtr^.RemoveChild(Index);
  101.    end;
  102.  
  103. {
  104.  NAME:          TNode.Brother
  105.  INPUT:         Brother Index : integer
  106.  OUTPUT:        PNode
  107.  PURPOSE:       Returns the pointer to a brother
  108.                 0 returns it's own pointer
  109.                 nil is returned if brother does not exist
  110. }
  111. function TNode.Brother(ItemCount:integer):PNode;
  112. var  i:integer;
  113.      MyBrotherPtr:PNode;
  114. begin
  115.    if ItemCount=0 then begin
  116.       Brother:=@Self;
  117.       exit;
  118.       end;
  119.    MyBrotherPtr:=BrotherNodePtr;
  120.    {if BrotherNodePtr=nil then begin
  121.       Brother:=nil;
  122.       exit;
  123.       end;}
  124.  
  125.    for i:=1 to ItemCount-1 do begin
  126.        if MyBrotherPtr=nil then begin
  127.           Brother:=nil;
  128.           exit;
  129.           end;
  130.        {if MyBrotherPtr^.BrotherNodePtr=nil then
  131.        if i<ItemCount-1 then begin
  132.           Brother:=nil;
  133.           exit;
  134.           end
  135.           else break;}
  136.        MyBrotherPtr:=MyBrotherPtr^.BrotherNodePtr;
  137.        end;
  138.    Brother:=MyBrotherPtr;
  139.    end; {TNode.Brother}
  140.  
  141. {
  142.  NAME:          TNode.Child
  143.  INPUT:         Child Index : integer
  144.  OUTPUT:        PNode
  145.  PURPOSE:       returns a pointer to ItemCount 'th child
  146.                 nil of none or no such child
  147. }
  148. function TNode.Child(ItemCount:integer):PNode;
  149. var
  150.    i:integer;
  151.    MyBrotherPtr:PNode;
  152. begin
  153.    if Self.ChildNodePtr=nil then begin
  154.       Child:=nil;
  155.       exit;
  156.       end;
  157.    MyBrotherPtr:=Self.ChildNodePtr;
  158.    for i:=0 to ItemCount-1 do begin
  159.        if MyBrotherPtr=nil then begin
  160.           Child:=nil;
  161.           exit;
  162.           end;
  163.       MyBrotherPtr:=MyBrotherPtr^.BrotherNodePtr;
  164.       end;
  165.   Child:=MyBrotherPtr;
  166.   end;
  167.  
  168. {
  169.  NAME:          TNode.RemoveBrother
  170.  INPUT:         Brother Index : integer
  171.  OUTPUT:        Boolean (True means operation successfull)
  172.  PURPOSE:       remove a brother of a node indexed by input
  173.  revisions:     20.05.96 (bug in last node removal)
  174. }
  175. function TNode.RemoveBrother(ItemPosition:integer):boolean;
  176. var
  177.      LinkPrevious:PNode;
  178.      LinkForward:PNode;
  179.      CurrentNode:PNode;
  180. begin
  181.      if ItemPosition=0 then begin
  182.       if BrotherNodePtr<>nil then begin
  183.          LinkForward:=BrotherNodePtr^.BrotherNodePtr;
  184.          BrotherNodePtr^.BrotherNodePtr:=nil;
  185.          Dispose(BrotherNodePtr,Destroy);
  186.          BrotherNodePtr:=LinkForward;
  187.          RemoveBrother:=True
  188.          end
  189.          else RemoveBrother:=False;
  190.      end
  191.      else begin
  192.        LinkPrevious:=BrotherNodePtr;
  193.        CurrentNode:=BrotherNodePtr;
  194.        while ItemPosition>0 do begin
  195.           ItemPosition:=ItemPosition-1;
  196.           if CurrentNode^.BrotherNodePtr=nil then begin
  197.              RemoveBrother:=False;
  198.              exit;
  199.              end;
  200.           LinkPrevious:=CurrentNode;
  201.           CurrentNode:=CurrentNode^.BrotherNodePtr;
  202.           end;
  203.        Linkforward:=CurrentNode^.BrotherNodePtr;
  204.        CurrentNode^.BrotherNodePtr:=nil;
  205.        Dispose(CurrentNode,Destroy);
  206.        if LinkPrevious<>nil then LinkPrevious^.BrotherNodePtr:=LinkForward;
  207.        RemoveBrother:=true;
  208.      end;
  209.      end;{TNode.RemoveBrother}
  210.  
  211. {
  212.  NAME:          TNode.RemoveChild
  213.  INPUT:         Child Index : integer
  214.  OUTPUT:        Boolean
  215.  PURPOSE:       Remove Indexed child from TNode
  216. }
  217. function TNode.RemoveChild(ItemPosition:integer):boolean;
  218. var
  219.     LinkForward:PNode;
  220. begin
  221.     if ItemPosition=0 then begin
  222.        if ChildNodePtr<>nil then begin
  223.           LinkForward:=ChildNodePtr^.BrotherNodePtr;
  224.           ChildNodePtr^.BrotherNodePtr:=nil;
  225.           Dispose(ChildNodePtr,Destroy);
  226.           ChildNodePtr:=LinkForward;
  227.           RemoveChild:=True;
  228.        end
  229.        else RemoveChild:=False;
  230.     end
  231.     else begin
  232.           RemoveChild:=ChildNodePtr^.RemoveBrother(ItemPosition-1);
  233.     end;
  234.     end;{TNode.RemoveChild}
  235.  
  236. {
  237.  NAME:          TNode.AddBrother
  238.  INPUT:         NodeType : ContentsType, NodeValue : string
  239.  OUTPUT:        PNode
  240.  PURPOSE:       Adds a brother with input contents and returns pointer to it
  241. }
  242. function TNode.AddBrother(ContentsType:ContentsType;Value:string):PNode;
  243. var
  244.     LastNodeBrother:PNode;
  245.     ANode:PNode;
  246. begin
  247.     New(ANode,Create(ContentsType,Value));
  248.     AddBrother:=ANode;
  249.     if BrotherNodePtr=nil then begin
  250.        BrotherNodePtr:=ANode;
  251.        Anode^.ParentNodePtr:=ParentNodePtr;
  252.     end
  253.     else begin
  254.     LastNodeBrother:=BrotherNodePtr;
  255.     while LastNodeBrother^.BrotherNodePtr<>nil do begin
  256.           LastNodeBrother:=LastNodeBrother^.BrotherNodePtr;
  257.     end;
  258.     LastNodeBrother^.BrotherNodePtr:=ANode;
  259.     Anode^.ParentNodePtr:=LastNodeBrother^.ParentNodePtr;
  260.     end;
  261.     end;{TNode.AddBrother}
  262.  
  263. {
  264.  NAME:          TNode.AddChild
  265.  INPUT:         NodeType : ContentsType, NodeValue : string
  266.  OUTPUT:        PNode
  267.  PURPOSE:       Adds a Child with input contents and returns a pointer to it
  268. }
  269. function TNode.AddChild(ContentsType:ContentsType;Value:string):PNode;
  270. var
  271.     LastNodeChild:PNode;
  272.     ANode:PNode;
  273. begin
  274.     New(ANode,Create(ContentsType,Value));
  275.     ANode^.ParentNodePtr:=@Self;
  276.     AddChild:=ANode;
  277.     if ChildNodePtr=nil then begin
  278.        ChildNodePtr:=ANode;
  279.     end
  280.     else begin
  281.     LastNodeChild:=ChildNodePtr;
  282.     while LastNodeChild^.BrotherNodePtr<>nil do begin
  283.           LastNodeChild:=LastNodeChild^.BrotherNodePtr;
  284.     end;
  285.     LastNodeChild^.BrotherNodePtr:=ANode;
  286.     end;
  287.     end;{TNode.AddChild}
  288.  
  289. {
  290.  NAME:          TNode.Create : constructor
  291.  INPUT:         NodeType : ContentsType, NodeValue: string
  292.  OUTPUT:        void
  293.  PURPOSE        Creates a new node by initializing field values and
  294.                 allocating contents record
  295. }
  296. constructor TNode.Create(ContentsType:ContentsType;Value:string);
  297. var
  298.     Code:integer;
  299.     i:extended;
  300. begin
  301.     New(NodeContents);
  302.     NodeType:=ContentsType;
  303.     Case ContentsType of
  304.          NodeSingle :  NodeContents^.MySingle:=Value;
  305.          NodeVariable: NodeContents^.MyVariable:=Value;
  306.          NodeOperator: NodeContents^.MyOperator:=Value;
  307.          NodeValue:    begin
  308.                        Val(Value,I,Code);
  309.                        NodeContents^.MyValue:=I;
  310.                        end;
  311.          end;
  312.     ChildNodePtr:=nil;
  313.     BrotherNodePtr:=nil;
  314.     ParentNodePtr:=nil;
  315.     end;{TNode constructor}
  316.  
  317. {
  318.  NAME:          TNode.Destroy : destructor
  319.  INPUT:         void
  320.  OUTPUT:        void
  321.  PURPOSE:       Disposes the node with it's children and brothers
  322.                 use Remove to link brothers without removing them
  323. }
  324. destructor TNode.Destroy;
  325. begin
  326.      if ChildNodePtr<>nil then Dispose(ChildNodePtr,Destroy);
  327.      if BrotherNodePtr<>nil then Dispose(BrotherNodePtr,Destroy);
  328.      Dispose(NodeContents);
  329.      end;{TNode destructor}
  330.  
  331. {
  332.  NAME:          TNode.Contents
  333.  INPUT:         void
  334.  OUTPUT:        string
  335.  PURPOSE:       returns string type for node contents
  336. }
  337. function TNode.Contents:string;
  338. var
  339.    NeedConvert:string;
  340. begin
  341.    case NodeType of
  342.      NodeVariable: Contents:=NodeContents^.MyVariable;
  343.      NodeOperator: Contents:=NodeContents^.MyOperator;
  344.      NodeValue:    begin
  345.                    Str(NodeContents^.MyValue:16:3,NeedConvert);
  346.                    Contents:=NeedConvert;
  347.                    end;
  348.      NodeSingle:   Contents:=NodeContents^.MySingle;
  349.      end;
  350.      end;{TNode.Contents}
  351.  
  352. {
  353.  NAME:          TNode.Show
  354.  INPUT:         level : integer , 0 is top level of a tree
  355.  OUTPUT:        standard output
  356.  PURPOSE:       writes the tree to standard output
  357. }
  358. procedure TNode.ShowLevel(level:integer;var ShowString:string);
  359. var
  360.    i:integer;
  361. begin
  362.      for i:=0 to level do ShowString:=ShowString+'  ';
  363.      ShowString:=ShowString+Contents+Chr(10)+Chr(13);
  364.      if ChildNodePtr<>nil then begin
  365.         ChildNodePtr^.ShowLevel(level+1,ShowString);
  366.         end;
  367.      if BrotherNodePtr<>nil then begin
  368.         BrotherNodePtr^.ShowLevel(level,ShowString);
  369.         end;
  370. end;
  371.  
  372. procedure TNode.Show;
  373. var
  374.    ShowString:string;
  375. begin
  376.      ShowString:='';
  377.      ShowLevel(0,ShowString);
  378.      MessageDlg(ShowString,mtInformation,[mbOk],0);
  379.      end;{TNode.Show}
  380.  
  381. {
  382.  NAME:          TNode.ChildCount
  383.  INPUT:         void
  384.  OUTPUT:        integer
  385.  PURPOSE:       counts the children of a node
  386. }
  387. function TNode.ChildCount:integer;
  388. var
  389.    ChildNode:PNode;
  390.    ChildCounter:integer;
  391. begin
  392.      ChildCounter:=0;
  393.      ChildNode:=ChildNodePtr;
  394.      while ChildNode<>nil do begin
  395.            ChildNode:=ChildNode^.BrotherNodePtr;
  396.            ChildCounter:=ChildCounter+1;
  397.            end;
  398.      ChildCount:=ChildCounter;
  399.      end;
  400.  
  401. {
  402.  NAME:          TNode.Parent
  403.  INPUT:         void
  404.  OUTPUT:        PNode
  405.  PURPOSE:       returns the pointer to parent node (if possible)
  406. }
  407. function TNode.Parent:PNode;
  408. begin
  409.      Parent:=@Self.ParentNodePtr^;
  410.      end;
  411.  
  412. {
  413.  NAME:          TNode.BrothersCount
  414.  INPUT:         void
  415.  OUTPUT:        integer
  416.  PURPOSE:       counts all brothers (self included)
  417.                 -2 means at top of tree and ParentNode inexistant
  418. }
  419. function TNode.BrothersCount:integer;
  420. begin
  421.      if ParentNodePtr<>nil then
  422.      BrothersCount:=ParentNodePtr^.ChildCount
  423.      else BrothersCount:=-2;
  424. end;
  425.  
  426. {
  427.  NAME:          TNode.Index
  428.  INPUT:         void
  429.  OUTPUT:        integer
  430.  PURPOSE:       returns the position of the node under the ParentNode
  431.                 -2 means no parent node
  432.                 -1 means the tree is corrupt
  433. }
  434. function TNode.Index:integer;
  435. var CurrentNode:PNode;
  436.     CurrentIndex:integer;
  437. begin
  438.    CurrentIndex:=0;
  439.    if ParentNodePtr=nil then begin
  440.       Index:=-2;        {returns -2 if first level of tree}
  441.       exit;
  442.       end;
  443.    CurrentNode:=ParentNodePtr^.ChildNodePtr;
  444.    if CurrentNode=@Self then begin
  445.       Index:=0;         {if first element, then zero position}
  446.       exit;
  447.       end;
  448.    while CurrentNode<>nil do begin
  449.       CurrentIndex:=CurrentIndex+1;
  450.       CurrentNode:=CurrentNode^.BrotherNodePtr;
  451.       if CurrentNode=nil then break;
  452.       if CurrentNode=@Self then begin
  453.          Index:=CurrentIndex;
  454.          exit;
  455.          end;
  456.       end;
  457.    Index:=-1;
  458.    end;
  459.  
  460. {
  461.  NAME:          TNode.InsertLevel
  462.  INPUT:         Node : PNode
  463.  OUTPUT:        PNode
  464.  PURPOSE:       - inserts a node into the tree that has no brothers,
  465.                 i.e. adds a whole vertical level to the tree
  466.                 - adds an item to the new node and returns pointer to it
  467.                 This is equal to push the node to the left and add a new
  468.                 right item on a binary tree
  469.  note:          pointers have shitty behavior, this seems to work...
  470.                 this routine has been rewritten at least 20 times...
  471. }
  472. function TNode.InsertLevel(BItem:PNode):PNode;
  473. var
  474.    NewNode:PNode;
  475. begin
  476.    New(NewNode,Create(NodeType,Contents));
  477.    NewNode^.NodeType:=NodeType;
  478.    NewNode^.NodeContents^:=NodeContents^;
  479.    NewNode^.ChildNodePtr:=ChildNodePtr;
  480.    NewNode^.BrotherNodePtr:=BrotherNodePtr;
  481.    NewNode^.ParentNodePtr:=@Self;
  482.    NodeType:=BItem^.NodeType;
  483.    NodeContents^:=BItem^.NodeContents^;
  484.    ChildNodePtr:=NewNode;
  485.    BrotherNodePtr:=nil;
  486.    InsertLevel:=AddChild(NodeValue,'0');
  487. end;
  488.  
  489. {TNode ends here}
  490.  
  491. end.
  492.